home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Graphics / GraphicsWorkshop / Source / Converters / PCX_SCRATCH / pcxtoppm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-14  |  7.9 KB  |  354 lines

  1. /*
  2.  * pcxtoppm.c - Converts from a PC Paintbrush PCX file to a PPM file.
  3.  *
  4.  * Copyright (c) 1990 by Michael Davidson
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software and its
  7.  * documentation for any purpose and without fee is hereby granted,
  8.  * provided that the above copyright notice appear in all copies and that
  9.  * both that copyright notice and this permission notice appear in
  10.  * supporting documentation.
  11.  *
  12.  * This file is provided AS IS with no warranties of any kind.  The author
  13.  * shall have no liability with respect to the infringement of copyrights,
  14.  * trade secrets or any patents by this file or any part thereof.  In no
  15.  * event will the author be liable for any lost revenue or profits or
  16.  * other special, indirect and consequential damages.
  17.  *
  18.  */
  19.  
  20. #include    <stdio.h>
  21. #include    "ppm.h"
  22.  
  23. #define    PCX_MAGIC    0x0a        /* PCX magic number        */
  24. #define    PCX_HDR_SIZE    128        /* size of PCX header        */
  25. #define    PCX_256_COLORS    0x0c        /* magic number for 256 colors    */
  26.  
  27. #define    MAXCOLORS       256
  28. #define    MAXPLANES    4
  29. #define    PCX_MAXVAL    255
  30.  
  31. static void read_pcx_image ARGS(( FILE *fp, unsigned char *buf, int BytesPerLine, int Planes, int Height ));
  32. static void pcx_planes_to_pixels ARGS(( unsigned char *pixels, unsigned char *bitplanes, int bytesperline, int planes, int bitsperpixel ));
  33. static void pcx_unpack_pixels ARGS(( unsigned char *pixels, unsigned char *bitplanes, int bytesperline, int planes, int bitsperpixel ));
  34. static int GetByte ARGS(( FILE *fp ));
  35. static int GetWord ARGS(( FILE *fp ));
  36.  
  37. void
  38. main(argc, argv)
  39.     int        argc;
  40.     char    *argv[];
  41. {
  42.     register int    i;
  43.     FILE        *ifp;
  44.     char        *ifname;
  45.     int            Version;
  46.     int            Xmin, Ymin, Xmax, Ymax;
  47.     int            Width, Height;
  48.     register int    x, y;
  49.     int            Planes;
  50.     int            BitsPerPixel;
  51.     int            BytesPerLine;
  52.     unsigned char    Red[MAXCOLORS], Green[MAXCOLORS], Blue[MAXCOLORS];
  53.     unsigned char    *pcximage;
  54.     unsigned char    *pcxplanes;
  55.     unsigned char    *pcxpixels;
  56.     pixel        **pixels;
  57.  
  58.     ppm_init( &argc, argv );
  59.  
  60.     switch (argc)
  61.     {
  62.      case 1:
  63.          ifname    = "standard input";
  64.          ifp    = stdin;
  65.          break;
  66.      case 2:
  67.          ifname    = argv[1];
  68.          ifp    = pm_openr(ifname);
  69.          break;
  70.      default:
  71.          pm_usage("[pcxfile]");
  72.          break;
  73.     }
  74.  
  75.     /*
  76.      * read the PCX header
  77.      */
  78.     if (GetByte(ifp) != PCX_MAGIC)
  79.      pm_error("%s is not a PCX file", ifname );
  80.  
  81.     Version    = GetByte(ifp);     /* get version #            */
  82.  
  83.     if (GetByte(ifp) != 1)     /* check for PCX run length encoding    */
  84.      pm_error("%s has unknown encoding scheme", ifname );
  85.  
  86.     BitsPerPixel= GetByte(ifp);
  87.     Xmin    = GetWord(ifp);
  88.     Ymin    = GetWord(ifp);
  89.     Xmax    = GetWord(ifp);
  90.     Ymax    = GetWord(ifp);
  91.  
  92.     Width    = (Xmax - Xmin) + 1;
  93.     Height    = (Ymax - Ymin) + 1;
  94.  
  95.     (void) GetWord(ifp);        /* ignore horizontal resolution    */
  96.     (void) GetWord(ifp);        /* ignore vertical resolution    */
  97.  
  98.     /*
  99.      * get the 16-color color map
  100.      */
  101.     for (i = 0; i < 16; i++)
  102.     {
  103.      Red[i]       = GetByte(ifp);
  104.      Green[i]  = GetByte(ifp);
  105.      Blue[i]   = GetByte(ifp);
  106.     }
  107.  
  108.     (void) GetByte(ifp);        /* skip reserved byte     */
  109.     Planes    = GetByte(ifp);        /* # of color planes     */
  110.     BytesPerLine= GetWord(ifp);        /* # of bytes per line     */
  111.     (void) GetWord(ifp);        /* ignore palette info     */
  112.  
  113.     /*
  114.      * check that we can handle this image format
  115.      */
  116.     switch (BitsPerPixel)
  117.     {
  118.     case 1:
  119.         if (Planes > 4)
  120.         pm_error("can't handle image with more than 4 planes");
  121.         break;
  122.  
  123.     case 2:
  124.     case 4:
  125.     case 8:
  126.         if (Planes == 1)
  127.         break;
  128.     default:
  129.         pm_error("can't handle %d bits per pixel image with %d planes",
  130.             BitsPerPixel,Planes);
  131.     }
  132.  
  133.  
  134.     /*
  135.      * read the pcx format image
  136.      */
  137.     fseek(ifp, (long)PCX_HDR_SIZE, 0);
  138.     pcximage    = (unsigned char *)pm_allocrow(BytesPerLine * Planes, Height);
  139.     read_pcx_image(ifp, pcximage, BytesPerLine, Planes, Height);
  140.  
  141.     /*
  142.      * 256 color images have their color map at the end of the file
  143.      * preceeded by a magic byte
  144.      */
  145.     if (BitsPerPixel == 8)
  146.     {
  147.     if (GetByte(ifp) != PCX_256_COLORS)
  148.         pm_error("bad color map signature" );
  149.  
  150.     for (i = 0; i < MAXCOLORS; i++)
  151.     {
  152.         Red[i]    = GetByte(ifp);
  153.         Green[i]    = GetByte(ifp);
  154.         Blue[i]    = GetByte(ifp);
  155.     }
  156.     }
  157.  
  158.     pixels    = ppm_allocarray(Width, Height);
  159.     pcxpixels    = (unsigned char *)pm_allocrow(Width+7, 1);
  160.  
  161.     /*
  162.      * convert the image
  163.      */
  164.     for (y = 0; y < Height; y++)
  165.     {
  166.      pcxplanes = pcximage + (y * BytesPerLine * Planes);
  167.  
  168.      if (Planes == 1)
  169.      {
  170.          pcx_unpack_pixels(pcxpixels, pcxplanes,
  171.           BytesPerLine, Planes, BitsPerPixel);
  172.      }
  173.      else
  174.      {
  175.          pcx_planes_to_pixels(pcxpixels, pcxplanes,
  176.           BytesPerLine, Planes, BitsPerPixel);
  177.      }
  178.  
  179.      for (x = 0; x < Width; x++)
  180.      {
  181.          i = pcxpixels[x];
  182.          PPM_ASSIGN(pixels[y][x], Red[i], Green[i], Blue[i]);
  183.      }
  184.     }
  185.  
  186.     pm_close(ifp);
  187.  
  188.     ppm_writeppm(stdout, pixels, Width, Height, (pixval) 255, 0 );
  189.  
  190.     exit(0);
  191. }
  192.  
  193. static void
  194. read_pcx_image(fp, buf, BytesPerLine, Planes, Height)
  195.     FILE    *fp;
  196.     unsigned char   *buf;
  197.     int         BytesPerLine;
  198.     int         Planes;
  199.     int         Height;
  200. {
  201.     int        c;
  202.     int        nbytes;
  203.     int        count;
  204.  
  205.     nbytes    = BytesPerLine * Planes * Height;
  206.  
  207.     while (nbytes > 0)
  208.     {
  209.      c    = GetByte(fp);
  210.      if ((c & 0xc0) != 0xc0)
  211.      {
  212.          *buf++    = c;
  213.          --nbytes;
  214.          continue;
  215.      }
  216.  
  217.      count    = c & 0x3f;
  218.      c    = GetByte(fp);
  219.      if (count > nbytes)
  220.          pm_error("repeat count spans end of image, count = %d, nbytes = %d", count, nbytes);
  221.  
  222.      nbytes    -= count;
  223.      while (--count >= 0)
  224.          *buf++ = c;
  225.     }
  226. }
  227.  
  228. /*
  229.  * convert multi-plane format into 1 pixel per byte
  230.  */
  231. static void
  232. pcx_planes_to_pixels(pixels, bitplanes, bytesperline, planes, bitsperpixel)
  233. unsigned char    *pixels;
  234. unsigned char    *bitplanes;
  235. int        bytesperline;
  236. int         planes;
  237. int         bitsperpixel;
  238. {
  239.     int     i, j;
  240.     int     npixels;
  241.     unsigned char    *p;
  242.  
  243.     if (planes > 4)
  244.      pm_error("can't handle more than 4 planes" );
  245.     if (bitsperpixel != 1)
  246.      pm_error("can't handle more than 1 bit per pixel" );
  247.  
  248.     /*
  249.      * clear the pixel buffer
  250.      */
  251.     npixels = (bytesperline * 8) / bitsperpixel;
  252.     p    = pixels;
  253.     while (--npixels >= 0)
  254.      *p++ = 0;
  255.  
  256.     /*
  257.      * do the format conversion
  258.      */
  259.     for (i = 0; i < planes; i++)
  260.     {
  261.      int pixbit, bits, mask;
  262.  
  263.      p    = pixels;
  264.      pixbit    = (1 << i);
  265.      for (j = 0; j < bytesperline; j++)
  266.      {
  267.          bits = *bitplanes++;
  268.          for (mask = 0x80; mask != 0; mask >>= 1, p++)
  269.           if (bits & mask)
  270.               *p |= pixbit;
  271.      }
  272.      }
  273. }
  274.  
  275. /*
  276.  * convert packed pixel format into 1 pixel per byte
  277.  */
  278. static void
  279. pcx_unpack_pixels(pixels, bitplanes, bytesperline, planes, bitsperpixel)
  280. unsigned char   *pixels;
  281. unsigned char   *bitplanes;
  282. int        bytesperline;
  283. int         planes;
  284. int         bitsperpixel;
  285. {
  286.     register int    bits;
  287.  
  288.     if (planes != 1)
  289.      pm_error("can't handle packed pixels with more than 1 plane" );
  290.     if (bitsperpixel == 8)
  291.     {
  292.     while (--bytesperline >= 0)
  293.         *pixels++ = *bitplanes++;
  294.     }
  295.     else if (bitsperpixel == 4)
  296.     {
  297.     while (--bytesperline >= 0)
  298.     {
  299.         bits    = *bitplanes++;
  300.         *pixels++    = (bits >> 4) & 0x0f;
  301.         *pixels++    = (bits     ) & 0x0f;
  302.     }
  303.     }
  304.     else if (bitsperpixel == 2)
  305.     {
  306.     while (--bytesperline >= 0)
  307.     {
  308.         bits    = *bitplanes++;
  309.         *pixels++    = (bits >> 6) & 0x03;
  310.         *pixels++    = (bits >> 4) & 0x03;
  311.         *pixels++    = (bits >> 2) & 0x03;
  312.         *pixels++    = (bits     ) & 0x03;
  313.     }
  314.     }
  315.     else if (bitsperpixel == 1)
  316.     {
  317.     while (--bytesperline >= 0)
  318.     {
  319.         bits    = *bitplanes++;
  320.         *pixels++    = ((bits & 0x80) != 0);
  321.         *pixels++    = ((bits & 0x40) != 0);
  322.         *pixels++    = ((bits & 0x20) != 0);
  323.         *pixels++    = ((bits & 0x10) != 0);
  324.         *pixels++    = ((bits & 0x08) != 0);
  325.         *pixels++    = ((bits & 0x04) != 0);
  326.         *pixels++    = ((bits & 0x02) != 0);
  327.         *pixels++    = ((bits & 0x01) != 0);
  328.     }
  329.     }
  330. }
  331.  
  332. static int
  333. GetByte(fp)
  334. FILE    *fp;
  335. {
  336.     int    c;
  337.  
  338.     if ((c = getc(fp)) == EOF)
  339.      pm_error("unexpected end of file" );
  340.  
  341.     return c;
  342. }
  343.  
  344. static int
  345. GetWord(fp)
  346. FILE    *fp;
  347. {
  348.     int    c;
  349.  
  350.     c  = GetByte(fp);
  351.     c |= (GetByte(fp) << 8);
  352.     return c;
  353. }
  354.